#pragma once
#include "Block_Cipher.h"


const uint SINGLE_KEY_LENGTH=0x100/BITS_IN_UINT;
const uint KEY_LENGTH=0x100/BITS_IN_UINT;

class GOST_Cipher: public Block_Cipher
{
public:	
	GOST_Cipher(const uint key[KEY_LENGTH]);
	GOST_Cipher(const uint key[KEY_LENGTH], const init_vector);

	text *Encipher(const text &plain, MODE = ECB);
	text *Decipher(const text &cipher, MODE = ECB);
	init_vector Get_Hash(const text &plain);
private:
	void init(const uint key[]);
	void set_key(const uint key[KEY_LENGTH]);
	void set_key(const init_vector key);
	//=========CIPHER CHARACTERICS===========//
	static const uint ROUNDS=0x20;
	static const uint SUB=0x4;
	static const uint INSUB=0x10;
	static const uint SHIFT=11;
	static const uint EIGHT=8;
	//=============KEY ELEMENTS==============//
	static const uint S[EIGHT][INSUB];
	uint KEY[KEY_LENGTH];
	init_vector iv;
	//================LOGIC==================//
	block feistel(const block, ubyte iter, DIRECTION) const;
	uint f(const uint a, const uint k) const;
	block E(const block);
	block D(const block);
	//////////////////
	block temk_E(block x);
	block temk_D(block x);
	block fe_E(block x);
	block fe_D(block x);
};